package com.sunlands.zlcx.usercenter.exception;

import com.sunlands.zlcx.usercenter.common.interceptor.AutoLogAspect;
import com.sunlands.zlcx.usercenter.util.AddressUtils;
import com.sunlands.zlcx.usercenter.util.DingUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.http.util.Asserts;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;


/**
 * Created with IntelliJ IDEA.
 * User: xiyuefei
 * Date: 2018/4/8
 * Time: 下午3:35
 */
@Data
@Component
@Slf4j
public class SendExceptionUtil {
    @Value("${spring.application.name}")
    private String sysinfo;
    @Value("${spring.profiles.active}")
    private String sysdev;

    @Resource(name = "sendError")
    private AsyncTaskExecutor sendError;
    @Autowired
    private DingUtil dingUtil;

    Timer timer = new Timer();
    private static ConcurrentHashMap<String, Integer> limiterMap = new ConcurrentHashMap();

    /**
     * 平台邮件报警限流方法，根据异常类型分类一分钟只发送用同一种异常一封邮件
     *
     * @param emailTitle
     * @param msg
     * @param ex
     */
    public synchronized void sendEmail(String emailTitle, String msg, Exception ex) {
        Asserts.notBlank(emailTitle, "邮件标题不能为空");
        Asserts.notBlank(msg, "邮件内容不能为空");
        Date now = new Date();
        sendError.execute(() -> {
            try {
                delaySend(emailTitle, msg, ex, now);
            } catch (Exception e) {
                log.error("发送邮件异常，e={}", e);
            }
        });
    }

    private synchronized void delaySend(String emailTitle, String msg, Exception ex, Date now) {
        SimpleDateFormat sdfAll = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String key = ex.getClass().getName() + "_" + sdfAll.format(new Date());
        String requestId = MDC.get(AutoLogAspect.REQUEST_ID);
        if (limiterMap.get(key) != null) {
            limiterMap.put(key, limiterMap.get(key) + 1);
            return;
        }
        limiterMap.put(key, 1);

        // 一分钟后发送邮件

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    log.info("emailTitle = {},msg = {} 一分钟发生次数 = {}", emailTitle, msg, limiterMap.get(key));
//                    InetAddress address = InetAddress.getLocalHost();
                    String hostAddress = AddressUtils.getInnetIp();
                    StringBuilder sb = new StringBuilder();
                    String emailTitleFlag = emailTitle + " [" + limiterMap.get(key) + "次" + "]";
                    sb.append("# " + emailTitle)
                            .append("\n")
                            .append("1. [一分钟发生次数")
                            .append(limiterMap.get(key))
                            .append("次]")
                            .append("\n")
                            .append("2. [ip]：")
                            .append(hostAddress)
                            .append(msg)
                            .append("\n")
                            .append("7. [Exception详情]：")
                            .append(ex.fillInStackTrace());
                    String result;
                    if (StringUtils.isNotBlank(requestId)) {
                        String url = dingUtil.getLogUrl() + URLEncoder.encode("[\"now-24h\",\"now\",\"Loki\",{\"expr\":\"{namespace=\\\"tongzhuo\\\"}|= \\\"" + requestId + "\\\"\"},{\"mode\":\"Logs\"},{\"ui\":[true,true,true,\"signature\"]}]", "utf-8") + "&pc_slide=false";
                        sb.append("\n  [日志链路]")
                                .append("(")
                                .append(url)
                                .append(")");
                        long endTime = now.getTime() + (1000 * 5);
                        String exceptionLogUrl = dingUtil.getLogUrl() + URLEncoder.encode("[\"" + now.getTime() + "\",\"" + endTime + "\",\"Loki\",{\"expr\":\"{namespace=\\\"tongzhuo\\\"}\"},{\"mode\":\"Logs\"},{\"ui\":[true,true,true,\"signature\"]}]", "utf-8") + "&pc_slide=false";
                        sb.append("  [异常详情日志]")
                                .append("(")
                                .append(exceptionLogUrl)
                                .append(")");
                    }
                    result = dingUtil.sendActionCard(emailTitleFlag, sb.toString(), null);
                    //发送邮件后清除记录
                    limiterMap.remove(key);
                    log.info("发送邮件结果：{}", result);
                } catch (Exception e) {
                    log.error("发送邮件异常，e={}", e);
                }

            }
        }, 1000 * 60);
    }

    public void sendEmail(String emailTitle, String msg) {

        Asserts.notBlank(emailTitle, "邮件标题不能为空");
        Asserts.notBlank(msg, "邮件内容不能为空");
        sendError.execute(() -> {
            try {
                log.info("sendEmail emails={},emailTitle={},msg={}", emailTitle, msg);
                InetAddress address = InetAddress.getLocalHost();
                String hostAddress = address.getHostAddress();
                StringBuilder sb = new StringBuilder();
                sb.append("# " + emailTitle)
                        .append("\n")
                        .append("1. [ip]：")
                        .append(hostAddress)
                        .append(msg);
                String result = dingUtil.sendActionCard(emailTitle, sb.toString(), null);
                log.info("发送邮件结果：{}", result);
            } catch (Exception e) {
                log.error("", e);
            }
        });

    }

    public void sendException(String msg) {
        sendEmail("系统异常[" + sysinfo + "]", msg);
    }

    public void sendException(String msg, Exception e) {
        log.info("exception sendemail msg={}", msg);
//        if (WebAppConfigurer.isDev()) {
//            log.warn("本地调试不发邮件！");
//            return;
//        }
        msg = "\n3. [requestId]：" + MDC.get(AutoLogAspect.REQUEST_ID) + msg;
        sendEmail("系统异常[" + sysinfo + "]", msg, e);
    }


}
